#ifndef __SUBSYSTEM_FIRE_BLOCK_BEHAVIOR_H__
#define __SUBSYSTEM_FIRE_BLOCK_BEHAVIOR_H__

#include <set>
#include <mutex>
#include "Engine/Point3.hpp"
#include "SubsystemPollableBlockBehavior.hpp"
#include "GameLock.hpp"


using namespace PocketSurvival::Engine;

namespace PocketSurvival
{
    class SubsystemTimeOfDay;
    class SubsystemTerrain;
    class SubsystemGameInfo;

    // 火焰行为，燃烧及扩散
    class SubsystemFireBlockBehavior : public SubsystemPollableBlockBehavior
    {
    protected:
        struct FireData
        {
            Point3 point;
            float time0;
            float time1;
            float time2;
            float time3;
            float time5;
            float fireExpandability;
        };

    protected:
        SubsystemTimeOfDay *m_timeOfDay;
        SubsystemTerrain *m_terrain;
        SubsystemGameInfo *m_gameInfo;

        static std::vector<Point3> ExpansionVec;
        std::vector<FireData> m_fireHandleVec;
        int32_t m_fireHandleVecIndex;

        std::map<Point3, float> m_toBurnAway;
        std::map<Point3, float> m_toExpand;

        std::map<Point3, FireData> m_fireDataMap;
        SpinLock m_fireDataMapLock;

        int32_t m_copyIndex;
        double m_lastScanTime;
        float m_lastScanDuration;
        float m_fireDiffusionReduction = 0.85f;

    protected:
        void initializeFireDataTimes(FireData &fireData);
        void initializeFireDataTime(FireData &fireData, int32_t face);
        void addFire(const Point3 &point, float expandability);
        void addFireNet(const Point3 &point, float expandability);
        void removeFire(const Point3 &point);
        void removeFireNet(const Point3 &point);

    public:
        bool isCellOnFire(const Point3 &point);
        bool setCellOnFire(const Point3 &point, float fireExpandability, ComponentMiner *miner = nullptr);
        void queueBurnAway(const Point3 &point, float expandability);

        virtual void onPoll(int32_t value, int32_t x, int32_t y, int32_t z) override;
        virtual void onNeighborBlockChanged(int32_t x, int32_t y, int32_t z, int32_t neighborX, int32_t neighborY, int32_t neighborZ) override;
        virtual void onBlockAdded(int32_t value, int32_t oldValue, int32_t x, int32_t y, int32_t z) override;
        virtual void onBlockRemoved(int32_t value, int32_t newValue, int32_t x, int32_t y, int32_t z) override;
        virtual void onBlockGenerated(int32_t value, int32_t x, int32_t y, int32_t z, bool isLoaded) override;
        virtual void onChunkDiscarding(TerrainChunk *chunk) override;

    public:
        SubsystemFireBlockBehavior();

        virtual void update(float dt) override;
        virtual void load(const nlohmann::json &json) override;

        virtual const std::string &getName() const override;
        virtual SubUpdateType getUpdateType() override;
    };

}

#endif
